package plp;



import java.awt.*;

import java.util.*;

import javax.swing.text.*;



class HLCode extends DefaultStyledDocument

{



	private static final long serialVersionUID = 1L;



	private static Hashtable<String, Object> chaves,funcoes;



	DefaultStyledDocument doc; 

	MutableAttributeSet normal;

	MutableAttributeSet palavrasChave;

	MutableAttributeSet comentarios;

	MutableAttributeSet aspas;

	MutableAttributeSet funcoesInt;

	MutableAttributeSet numeros;



	public HLCode()

	{

		doc = this;

		putProperty( DefaultEditorKit.EndOfLineStringProperty, "\n" );



		normal = new SimpleAttributeSet();

		StyleConstants.setForeground(normal, Color.black);



		comentarios = new SimpleAttributeSet();

		StyleConstants.setForeground(comentarios, Color.green);

		StyleConstants.setItalic(comentarios, true);



		palavrasChave = new SimpleAttributeSet();

		StyleConstants.setForeground(palavrasChave, Color.blue);

		StyleConstants.setBold(palavrasChave, true);



		aspas = new SimpleAttributeSet();

		StyleConstants.setForeground(aspas, Color.red);

		StyleConstants.setBold(aspas, false);

		StyleConstants.setItalic(aspas, false);



		funcoesInt = new SimpleAttributeSet();

		StyleConstants.setForeground(funcoesInt, Color.magenta);

		StyleConstants.setBold(funcoesInt, true);



		numeros = new SimpleAttributeSet();

		StyleConstants.setForeground(numeros, Color.orange);

		StyleConstants.setBold(numeros, false);



	}



	public static void BeginHashtable()

	{

		Object dummyObject = new Object();

		chaves = new Hashtable<String, Object>();

		chaves.put( "var", dummyObject );

		chaves.put( "skip", dummyObject );

		chaves.put( "while", dummyObject );

		chaves.put( "do", dummyObject );

		chaves.put( "read", dummyObject );

		chaves.put( "write", dummyObject );

		chaves.put( "if", dummyObject );

		chaves.put( "then", dummyObject );

		chaves.put( "else", dummyObject );

		chaves.put( "new", dummyObject );

		chaves.put( "this", dummyObject );

		chaves.put( "classe", dummyObject );

		chaves.put( "null", dummyObject );

		chaves.put( "do", dummyObject );

		chaves.put( "proc", dummyObject );

		chaves.put( "int", dummyObject );

		chaves.put( "boolean", dummyObject );

		chaves.put( "string", dummyObject );

		chaves.put( "let", dummyObject );

		chaves.put( "fun", dummyObject );

		chaves.put( "in", dummyObject );

		chaves.put( "call", dummyObject );

		chaves.put( "fn", dummyObject );

		chaves.put( "head", dummyObject );

		chaves.put( "tail", dummyObject );

		chaves.put( "for", dummyObject );

		chaves.put( "and", dummyObject);

		chaves.put( "or", dummyObject);

		chaves.put( "not", dummyObject);



		Object dummyObject1 = new Object();

		funcoes = new Hashtable<String, Object>();

		funcoes.put( "length", dummyObject1);

		funcoes.put( "true", dummyObject1);

		funcoes.put( "false", dummyObject1);

		funcoes.put( "vr", dummyObject1);

	}	



	public void insertString(int offset, String str, AttributeSet a) throws BadLocationException

	{

		super.insertString(offset, str, a);

		ProcLinhaModificadas(offset, str.length());

	}



	public void remove(int offset, int length) throws BadLocationException

	{

		super.remove(offset, length);

		ProcLinhaModificadas(offset, 0);

	}



	public void ProcLinhaModificadas(int offset, int length) throws BadLocationException

	{

		String content = doc.getText(0, doc.getLength());



		Element root = doc.getDefaultRootElement();

		int startLine = root.getElementIndex( offset );

		int endLine = root.getElementIndex( offset + length );



		for (int i = startLine; i <= endLine; i++)

		{

			int startOffset = root.getElement( i ).getStartOffset();

			int endOffset = root.getElement( i ).getEndOffset();

			AplicarHighlighting(content, startOffset, endOffset - 1);

		}

	}



	public void AplicarHighlighting(String content, int startOffset, int endOffset)

	throws BadLocationException

	{

		int index;

		int lineLength = endOffset - startOffset;

		int contentLength = content.length();



		if (endOffset >= contentLength) endOffset = contentLength - 1;



		doc.setCharacterAttributes(startOffset, lineLength, normal, true);



		String multiLineStartDelimiter = "/*";

		String multiLineEndDelimiter = "*/";



		index = content.lastIndexOf( multiLineStartDelimiter, endOffset );



		if (index > -1)

		{

			int index2 = content.indexOf( multiLineEndDelimiter, index );



			if ( (index2 == -1) || (index2 > endOffset) )

			{

				doc.setCharacterAttributes(index, endOffset - index + 1, comentarios, false);

				return;

			}

			else

				if (index2 >= startOffset)

				{

					doc.setCharacterAttributes(index, index2 + 2 - index, comentarios, false);

					return;

				}

		}



		String singleLineDelimiter = "//";



		index = content.indexOf( singleLineDelimiter, startOffset );



		if ( (index > -1) && (index < endOffset) )

		{

			doc.setCharacterAttributes(index, endOffset - index + 1, comentarios, false);

			endOffset = index - 1;

		}



		checkForTokens(content, startOffset, endOffset);



	}



	private void checkForTokens(String content, int startOffset, int endOffset)

	{

		while (startOffset <= endOffset)

		{

			while ( isDelimiter( content.substring(startOffset, startOffset + 1) ) )

			{

				if (startOffset < endOffset) 

					startOffset++;

				else 

					return;

			}



			if ( isQuoteDelimiter( content.substring(startOffset, startOffset + 1) ) )

				startOffset = getQuoteToken(content, startOffset, endOffset);

			else

				startOffset = getOtherToken(content, startOffset, endOffset);

		}

	}



	private boolean isDelimiter(String character)

	{

		String operands = ";:{}()[]+-/%<=>!&|^~*";



		if (Character.isWhitespace( character.charAt(0) ) ||

				operands.indexOf(character) != -1 )

			return true;

		else

			return false;

	}



	private boolean isQuoteDelimiter(String character)

	{

		String quoteDelimiters = "\"'";



		if (quoteDelimiters.indexOf(character) == -1)

			return false;

		else

			return true;

	}



	private boolean isKeyword(String token)

	{

		Object o = chaves.get( token );

		return o == null ? false : true;

	}



	private boolean isimpclasses1(String token)

	{

		Object o = funcoes.get( token );



		return o == null ? false : true;

	}	



	public boolean isNumeric( String token )  

	{  

		try  

		{  

			Long.parseLong( token ); 

			return true;  

		}  

		catch (Exception e)   

		{  

			return false;  

		}  

	} 



	private int getQuoteToken(String content, int startOffset, int endOffset)

	{

		String quoteDelimiter = content.substring(startOffset, startOffset + 1);

		String escapedDelimiter = "\\" + quoteDelimiter;



		int index;

		int endOfQuote = startOffset;



		index = content.indexOf(escapedDelimiter, endOfQuote + 1);



		while ( (index > -1) && (index < endOffset) )

		{

			endOfQuote = index + 1;

			index = content.indexOf(escapedDelimiter, endOfQuote);

		}



		index = content.indexOf(quoteDelimiter, endOfQuote + 1);



		if ( (index == -1) || (index > endOffset) ) endOfQuote = endOffset;

		else endOfQuote = index;



		doc.setCharacterAttributes(startOffset, endOfQuote - startOffset + 1, aspas, false);



		return endOfQuote + 1;

	}



	private int getOtherToken(String content, int startOffset, int endOffset)

	{

		int endOfToken = startOffset + 1;



		while ( endOfToken <= endOffset )

		{

			if ( isDelimiter( content.substring(endOfToken, endOfToken + 1) ) )

				break;



			endOfToken++;

		}



		String token = content.substring(startOffset, endOfToken);



		if ( isKeyword( token ) )

			doc.setCharacterAttributes(startOffset, endOfToken - startOffset, palavrasChave, false);



		if(isimpclasses1 ( token) )

			doc.setCharacterAttributes(startOffset, endOfToken - startOffset, funcoesInt, false);



		if(isNumeric ( token) )

			doc.setCharacterAttributes(startOffset, endOfToken - startOffset, numeros, false);



		return endOfToken + 1;

	}



}